package com.wujunshen.thread.lock.readwritelock;

import org.apache.commons.lang3.exception.ExceptionUtils;

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import lombok.extern.slf4j.Slf4j;

/**
 * @author frank woo(吴峻申) <br>
 *     email:<a href="mailto:frank_wjs@hotmail.com">frank_wjs@hotmail.com</a> <br>
 * @date 2020/7/16 03:04<br>
 */
@Slf4j
public class TheData {
  private final ReadWriteLock rwl = new ReentrantReadWriteLock();
  private Object data = null;

  public void get() {
    rwl.readLock().lock(); // 读锁开启，读线程均可进入
    try { // 用try finally来防止因异常而造成的死锁
      log.info("{} is ready to read", Thread.currentThread().getName());
      Thread.sleep(new Random().nextInt(100));
      log.info("{} have read data {}", Thread.currentThread().getName(), data);
    } catch (InterruptedException e) {
      log.info(ExceptionUtils.getStackTrace(e));
    } finally {
      rwl.readLock().unlock(); // 读锁解锁
    }
  }

  public void put(Object data) {
    rwl.writeLock().lock(); // 写锁开启，这时只有一个写线程进入
    try {
      log.info("{} is ready to write", Thread.currentThread().getName());
      Thread.sleep(new Random().nextInt(100));
      this.data = data;
      log.info("{} have write data {}", Thread.currentThread().getName(), data);
    } catch (InterruptedException e) {
      log.error(ExceptionUtils.getStackTrace(e));
    } finally {
      rwl.writeLock().unlock(); // 写锁解锁
    }
  }
}
